package icu.zqyhdm.blog.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import icu.zqyhdm.blog.constant.RedisConst;
import icu.zqyhdm.blog.vo.*;
import icu.zqyhdm.exception.MyException;
import icu.zqyhdm.helper.JwtHelper;
import icu.zqyhdm.result.ResultCodeEnum;
import icu.zqyhdm.blog.entity.Comment;
import icu.zqyhdm.blog.entity.User;
import icu.zqyhdm.blog.mapper.CommentMapper;
import icu.zqyhdm.blog.service.CommentService;
import icu.zqyhdm.blog.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @Description
 * @Author lifu
 * @Date 2021/6/23 9:40
 */
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public List<CommentVo> listAll() {
        return null;
    }

    /**
     * 查出所有评论以及部分子评论
     */
    @Override
    @Cacheable(value = "blog:commentList",keyGenerator ="keyGenerator")
    public CommentListVo list(Integer articleId, Integer current, Integer limit) {
        // 查询文章的总评论量
        Integer count = baseMapper.selectCount(new QueryWrapper<Comment>()
                .eq("article_id", articleId));
        CommentListVo commentListVo = new CommentListVo();
        commentListVo.setCount(count);
        //当评论为空
        if(count == 0){
            commentListVo.setCommentVo(new ArrayList<CommentVo>());
            return commentListVo;
        }

        // 查询redis的评论和回复的点赞数据
        Map<String,Integer> likeCountMap =(Map<String,Integer>) redisTemplate.opsForHash()
                .entries(RedisConst.COMMENT_LIKE_COUNT + articleId.toString());

        //分页查询评论
        List<CommentVo> commentVoList = baseMapper.listCommentByArticleId(articleId,current - 1,limit);
        // 提取评论id集合
        List<Integer> commentIdList = commentVoList.stream()
                .map(CommentVo::getId).collect(Collectors.toList());

        // 获取各评论的回复量
        List<ReplyCountDTO> replyCountDTOS = baseMapper.listReplyCountByCommentId(commentIdList);
        Map<String, Integer> replyCountMap = replyCountDTOS.stream()
                .collect(Collectors.toMap(replyCountDTO -> replyCountDTO.getParentCommentId().toString(), ReplyCountDTO::getReplyCount));

        // 处理各评论的回复内容
        // 根据评论id集合查询回复数据
        List<ReplyVo> replyVoList = baseMapper.listReplies(commentIdList);
        // 各个回复的点赞数
        for(ReplyVo replyVo : replyVoList){
            Integer likeCount = likeCountMap.get(replyVo.getId().toString());
            if(Objects.nonNull(likeCount)){
                replyVo.setLikeCount(likeCount);
            }
        }
        // 对评论进行分组
        Map<String, List<ReplyVo>> replyVoListMap = replyVoList.stream()
                .collect(Collectors.groupingBy(replyVo -> replyVo.getParentCommentId().toString()));

        // 最后封装评论的点赞量、回复内容、回复数量
        commentVoList.forEach(commentVo -> {
            Integer likeCount = likeCountMap.get(commentVo.getId().toString());
            if(likeCount != null){
                commentVo.setLikeCount(likeCount);
            }
            commentVo.setReplyCount(replyCountMap.get(commentVo.getId().toString()));
            commentVo.setReplyVoList(replyVoListMap.get(commentVo.getId().toString()));
        });
        commentListVo.setCommentVo(commentVoList);
        return commentListVo;
    }

    /**
     *  查询评论下的回复
     */
    @Override
    @Cacheable(value = "blog:commentList", keyGenerator ="keyGenerator")
    public List<ReplyVo> listRepliesByCommentId(Integer articleId, Integer commentId, Integer current, Integer limit) {
        List<ReplyVo> replyVoList = baseMapper.listRepliesByCommentId(commentId,current - 1,limit);
        // 查询redis的评论和回复的点赞数据
        Map<String,Integer> likeCountMap =(Map<String,Integer>) redisTemplate.opsForHash()
                .entries(RedisConst.COMMENT_LIKE_COUNT + articleId.toString());
        // 封装点赞数据
        for(ReplyVo replyVo : replyVoList){
            Integer likeCount = likeCountMap.get(replyVo.getId().toString());
            if(Objects.nonNull(likeCount)){
                replyVo.setLikeCount(likeCount);
            }
        }
        return replyVoList;
    }

    /**
     *  点赞评论
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "blog:commentList",allEntries = true)
    public void likeComment(String token, Integer articleId,Integer commentId) {
        // 判断是否点赞
        String commentLikeKey = RedisConst.COMMENT_USER_LIKE + JwtHelper.getUserId(token);
        if (redisTemplate.opsForSet().isMember(commentLikeKey, commentId.toString())) {
            // 点过赞则删除评论id
            redisTemplate.opsForSet().remove(commentLikeKey, commentId.toString());
            // 评论点赞量-1
            redisTemplate.opsForHash().increment(RedisConst.COMMENT_LIKE_COUNT + articleId.toString(), commentId.toString(), -1L);
        } else {
            // 未点赞则增加评论id
            redisTemplate.opsForSet().add(commentLikeKey, commentId);
            // 评论点赞量+1
            redisTemplate.opsForHash().increment(RedisConst.COMMENT_LIKE_COUNT + articleId.toString(), commentId.toString(), 1L);
        }
    }

    /**
     *  保存评论
     */
    @Override
    @CacheEvict(value = "blog:commentList",allEntries = true)
    public void saveComment(String token, CommentUploadVo commentUploadVo) {
        Comment comment = BeanUtil.copyProperties(commentUploadVo, Comment.class);
        Integer userId = JwtHelper.getUserId(token);
        comment.setAuthorId(userId);
        int i = baseMapper.insert(comment);
        if(i < 1){
            throw new MyException(ResultCodeEnum.NET_ERROR);
        }
    }

    /**
     *  删除文章的评论
     */
    @Override
    @Transactional(rollbackFor=Exception.class)
    @CacheEvict(value = "blog:commentList",allEntries = true)
    public void deleteCommentByArticleId(Integer articleId) {
        // 删除mysql表的记录
        baseMapper.delete(new QueryWrapper<Comment>().eq("article_id",articleId));
        // 删除redis记录
        redisTemplate.delete(RedisConst.COMMENT_LIKE_COUNT + articleId.toString());
    }
}
